分支限界求解货郎担/旅行商问题

 
/*   文件名: BoundleSalesMan.h   限界函数法    */
#pragma once
#include "salesman.h"
#include <vector>
#include "Node.h"
class BoundSalesMan :
     public SalesMan
{
protected:
     int SetIMatrix(int i,int k,vector<vector<int> > & im);// 生成第 i 点的规约矩阵 , 并返回约数 ,k 点为其父结点
     int Cost(vector<int> A); // 获取 A 中保存的路径的路径长度
     int SimMatrix(vector< vector<int> > & m); // m 规约
public: 
     void Travel();
};
/*  文件名: BoundleSalesMan.cpp   限界函数法    */
#include "StdAfx.h"
#include "BoundSalesMan.h"
#include "Node.h"
#include <queue>
#include <vector>
int BoundSalesMan::SimMatrix(vector<vector<int> > & m)
// m 规约
{
     int result=0;
     int col=(int)m.size()-1;
     bool boolMax,boolZone;
     // 对行进行规约
     for (int i=0;i<=col;i++)
     {
         boolMax=true,
         boolZone=false;
         for (int j=0;j<=col;j++)
         {
              boolMax=boolMax && (m[i][j]==MAXNUM); // 所有都是无穷大
              boolZone=boolZone || (m[i][j]==0) ; // 是否有一个是 0
         }
         if ((boolMax) || (boolZone))
         // 如果本行所有数据元素都是无穷大,或者有一个是 0 ,本行已经规约
              continue;// 继续下一行
         else  // 否则
         {
              // 从本行中找到最小的一个值,减去他,约数加上这个值
              int min=m[i][0];
              for (int k=1;k<=col;k++)
              {
                   if (min>m[i][k])
                       min=m[i][k];
              }
              for (int k=0;k<=col;k++)
              {
                   if (m[i][k]!=MAXNUM)  // 如果是无穷值,则不变
                    m[i][k]-=min;
              }
              result+=min;
         }
     }   
     // 对列进行规约
     for (int i=0;i<=col;i++)
     {
         boolMax=true,
         boolZone=false;
         for (int j=0;j<=col;j++)
         {
              boolMax=boolMax && (m[j][i]==MAXNUM); // 所有都是无穷大
              boolZone=boolZone || (m[j][i]==0) ; // 是否有一个是 0
         }
         if ((boolMax) || (boolZone))
         // 如果本列所有数据元素都是无穷大,或者有一个是 0 ,本列已经规约
              continue;// 继续下一列
         else  // 否则
         {
              // 从本列中找到最小的一个值,减去他,约数加上这个值
              int min=m[0][i];
              for (int k=1;k<=col;k++)
              {
                   if (min>m[k][i])
                       min=m[k][i];
              }
              for (int k=0;k<=col;k++)
              {
                   if (m[k][i]!=MAXNUM) // 如果是无穷值,则不变
                    m[k][i]-=min;
              }
              result+=min;
         }
     }
     return result;
}
int  BoundSalesMan::SetIMatrix(int i,int k,vector<vector<int> > & im)
// 生成第 i 点的规约矩阵
{
     int cols=im.size()-1;
     // 先将 k i 列置为无穷 /
     for (int j=0;j<=cols;j++)
     {
         im[k][j]=MAXNUM;  
         im[j][i]=MAXNUM;
     }
     // 再将 i 0 列置为无穷
     im[i][0]=MAXNUM;  
     // 再进行规约,记录规约值
     return SimMatrix(im);
}
 
int BoundSalesMan::Cost(vector<int> A)
// 获取 A 中保存的路径的路径长度
{
     int i=A.size();
     int sum=matrix[0][A[0]];// 先求从 0 到第一个点的距离
     for (unsigned int i=1;i<A.size();i++)
     {
         sum+=matrix[A[i-1]][A[i]];
     }
     sum+=matrix[A[i-1]][0];// 再加上最后一个点到 0 点的距离
     return sum;
}
void BoundSalesMan::Travel()
{
     path.clear();
     vector<vector<int> > simpleM=matrix; //0 点的规约矩阵
     int n0=SimMatrix(simpleM);
     int cols=matrix.size()-1;  
     priority_queue<Node> p;
     Node firstNode(n0,0,0,path,simpleM);
     p.push(firstNode);                    //0 结点入队列
     Node node;
     while (! p.empty() && p.top().level<cols )
     {
         node=p.top();
         p.pop();
         for (int i=1;i<=cols;i++)
         {
              for (int j=0;j<node.states.size();j++)
              {
                   if (i==node.states[j]) // 路径里有这个点了
                       break;
              }
              if (j<node.states.size())
                   continue; 
              // 否则
              simpleM=node.m;
              int tmp=node.num;
              tmp+=simpleM[node.position][i];
              tmp+=SetIMatrix(i,node.position ,simpleM); // 对第 i 点的矩阵进行处理                        vector<int> tmpPath=node.states;
              tmpPath.push_back(i);
              Node newNode(tmp,node.level+1,i,tmpPath,simpleM);
              p.push(newNode);
         }
     }
     path=p.top().states;
     cout<<"Bound MinValue:"<<Cost(path)<<endl;
     PrintPath();
}
 
/* 文件名: SalesMan 货郎担基类头文件   */
#pragma once
#include <vector>
#include <fstream>
using namespace std;
class SalesMan
{
protected:
     enum{MAXNUM=999}; // 最大值设为无穷大
     vector<vector<int> >  matrix; // 对应的邻接矩阵
     vector<int> path; // 记录走过的最小成本路径
     int minValue;// 最小路径长度
public:
     SalesMan();
     virtual ~SalesMan(){matrix.clear();path.clear();}
     void PrintMatrix(); // 打印矩阵值
     void PrintPath();  // 打印路径
     virtual void Travel(){}; // 主要寻找路径的函数,将在子类里面实现
};
/* 文件名: SalesMan Cpp 货郎担基类源文件   */
#include "StdAfx.h"
#include "SalesMan.h"
SalesMan::SalesMan() // 构造函数,从文件中读取数值,生成图的邻接矩阵,
{// 认为矩阵结点从 0 开始
     fstream fin("in.txt");
     if (!fin)
     {   
         cerr<<"file open failed!"<<endl;
         return;
     }
     int n;
     fin>>n;
     path.resize(n-1); // 路径记录中间的那些结点
     // 从文件里取值
     for (int i=0;i<n;i++)
     {
         vector<int> col;      
         for (int j=0;j<n;j++)
         {
              int num;
              fin>>num;
              col.push_back(num);
         }           
         matrix.push_back(col);
     }
     fin.close();
}
void SalesMan::PrintPath()
{
     cout<<0<<"/t";
     for (unsigned int i=0;i<path.size();i++)
         cout<<path[i]<<"/t";
     cout<<"0"<<endl;
}
void SalesMan::PrintMatrix()
{
     int n=(int)matrix.size();
     for (int i=0;i<n;i++)
     {
         for (int j=0;j<n;j++)
              cout<<matrix[i][j]<<"/t";
         cout<<endl;
     }
}
 
/* 文件名: Node.h  BoundSalesMan 所调用,结点数据结构 */
#pragma once
#include <vector>
using namespace std;
struct Node
{
public:
     int num;// 约数
     int level; // 层级
     int position; // 当前结点
     vector<vector<int> > m; // 当前结点的矩阵
     vector<int> states; // 当前路径状态集
     Node(){};
     Node(int n,int l,int position,vector<int> path,vector<vector<int> > mValue);
     bool operator< (const Node & B)const
     {
          return num>B.num;
     }
};
/* 文件名: Node.cpp  BoundSalesMan 所调用,结点数据结构的实现 */
#include "StdAfx.h"
#include "Node.h"
Node::Node(int n,int l,int pos,vector<int> path,vector<vector<int> > mValue)
{
     num=n;  level=l;  position=pos;  states=path;  m=mValue;
}
 
 
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值